#include <iostream>
#include <string>
using namespace std;

//C++为了规范类型转换，提供了四种强制类型转换。


//---------------------------
//static_cast ，一般只支持相近的类型，比如数与数
//reinterpret_cast,有些有关联，但是意义不明的强制类型转换
int Test_static_cast()
{
    const double pi = 3.14;
    int a = static_cast<int>(pi);
    int ptr =  static_cast<int>(pi);
    return 0;
}

int Test_reinterpret_cast()
{
    int a = 0;
    int *p = reinterpret_cast<int*>(a);
    return 0;
}

void func()
{

}
class A{
    public:
    void func()
    {

    }
};
int Test_const_cast()
{
    //const 常量，编译器有可能直接搞成常量或者，放进寄存器，所以修改内存的值没有影响到那个值
    const int a = 2;
    //加上volatile,就表示每次都到内存里面去取
    // volatile const int a = 2;
    int *p = const_cast<int*>(&a);
    *p = 3;
    cout<<"p::"<<p<<"||||"<<"&a::"<<(void*)&a<<endl;//由于C++IO流识别问题（也不能算作问题，只是没有都做重载，因为也可能做得完），这里volatile修饰的变量取地址就会导致识别成1，加个void*,或者使用printf来解决
    //C++的ostram里面，没有单独对每个这类指针进行重载，而其里面是存在把指针转换位bool类型的，空是0，非空是1，所以导致打印出结果为1
    //借助 std::boolalpha <<应该可以观察到打印值就是true,而一个非bool值是不会打印成true的
    //不只是volatile，还有函数指针，成员函数指针都是这种结果，且成员函数指针打印时强转(void*)还会警告
    //注意：：成员函数函数名不直接具备函数地址的功能，不和C语言一样,所以这里包含在函数装载器(function)处是一样的，都是要对成员函数取地址才能用
    // cout<< std::boolalpha << 1<<endl;
    // cout<<(void*)func<<endl;
    // cout<<(void*)&A::func<<endl;
    // printf("%p\n",(void*)&A::func);
    printf("%p\n",&a);
    cout<<a<<endl;//打印结果是2
    cout<<*p<<endl;
    return 0;
}


//----------------------------------
//dynamic_cast，用于多肽类的父子之间的指针转换

class Parent{
    virtual void func(){

    }
    protected:
    int a = 0;
};

class B :public Parent{
    public:
    int b[100000] ;
};
int Test_dynamic_cast()
{   
    B objb;
    Parent obja = objb;
    //子类给父类赋值的时候，可以理解成截取赋值，并非说是隐式类型转换，其证据就是隐式类型转换是要存在临时对象的，而临时对象具备常性，不可能像上述
    double pi = 3.14;
    const int a = pi;
    
    //C++里面通过强制类型转换，可以让子类指针指向父类，但是就会出现下面的问题，越界了
    B* pb = (B*)&obja;
    //会发现这里居然在访问本来obja里面不存在的数据，也就是越界访问了，这是很严重的问题。
    for(int i = 0;i<100000;i++)
    {
        pb->b[i] = i;
    }
    B* pb2 = dynamic_cast<B*>(&obja);//用dynamic去转换，就不会使得这个转换成功
    pb2->b[0]++;
    //C++里面，不允许父类对象转换位子类对象，但是指针和引用可以转换为子类指针和引用，其经典的引用就是
    return 0;
}

int main(){

    Test_reinterpret_cast();
    return 0;
}